package com.zhuzi.component;

import cn.hutool.core.util.StrUtil;
import com.google.common.collect.Maps;
import com.zhuzi.common.utils.BeanListUtils;
import com.zhuzi.dto.KzzAndStockDTO;
import com.zhuzi.entity.KzzAndStockEntity;
import com.zhuzi.repository.KzzAndStockEntityRepository;
import com.zhuzi.utils.JsoupHttpUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.jsoup.Connection;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author zhuzi
 * 2022/8/8 18:01
 * 宁稳网抓取可转债代码和股票代码
 */
@Slf4j
@Component
@RequiredArgsConstructor(onConstructor_ = {@Lazy})
public class KzzComponent {
    private static final String URL = "https://www.ninwin.cn/index.php?m=cb&show_cb_only=Y&show_listed_only=Y";
    private final static Function<Element, KzzAndStockDTO> eleToKzzStockDto = element -> {
        KzzAndStockDTO kzzAndStockDTO = new KzzAndStockDTO().setCbCode(element.attr("data-cbcode"))
                .setCbName(element.attr("data-cb_name"))
                .setStockCode(StringUtils.substring(element.attr("data-stock_code"), 2))
                .setStockName(element.attr("data-stock_name"));

        kzzAndStockDTO.setPrice(element.select("td:nth-child(9)").text());
        kzzAndStockDTO.setPremium(element.select("td:nth-child(16)").text());
        kzzAndStockDTO.setAmount(element.select("td.stock_price_id.remain_amount").text())

                .setRade(element.select("td:nth-child(23)").text())
                .setValuel(element.select("td:nth-child(17)").text());


        Elements cbPriceEle = element.select("td:nth-child(14)");
        kzzAndStockDTO.setMarker(element.select("td.market_cap").text());


        String cbPriceTax = cbPriceEle.attr("title");
        kzzAndStockDTO.setCbPrice(cbPriceEle.html()).setCbPriceTax(StringUtils.replace(cbPriceTax, "税后", ""));
        //剩余年限|
        Elements lessYear = element.select("td.cb_t_id.bond_t.bond_t1");
        kzzAndStockDTO.setLessYear(StrUtil.subBefore(lessYear.text(), "年", false));
        return kzzAndStockDTO;
    };
    static Map<String, String> cookieMap = Maps.newLinkedHashMap();
    static Map<String, String> headerMap = new HashMap<>(2);

    static {
        headerMap.put("Host", "www.ninwin.cn");
    }

    final KzzAndStockEntityRepository kzzAndStockEntityRepository;


    @Transactional(rollbackFor = Exception.class)
    public List<KzzAndStockEntity> getKzzAndStock() {
        try {
            Connection.Response response = JsoupHttpUtils.get(URL, headerMap, cookieMap, null);
            Map<String, String> cookies = response.cookies();
            if (MapUtils.isNotEmpty(cookies)) {
                cookieMap.putAll(cookies);
            }
            Document rootDoc = response.parse();
            Elements select = rootDoc.select("#cb_hq > tbody > tr");
            List<KzzAndStockDTO> collect = select.stream().map(eleToKzzStockDto).collect(Collectors.toList());
            List<KzzAndStockEntity> entityList = BeanListUtils.copyList(collect, KzzAndStockEntity::new);

            kzzAndStockEntityRepository.deleteFirstBy();
            kzzAndStockEntityRepository.saveAll(entityList);
            return entityList;
        } catch (Exception e) {
            log.error("解析可转债代码异常", e);
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        }
        return null;
    }

    /**
     * 得到所有
     *
     * @return {@link List}<{@link KzzAndStockEntity}>
     */
    public List<KzzAndStockEntity> getAll() {
        List<KzzAndStockEntity> all = kzzAndStockEntityRepository.findAll();
        if (CollectionUtils.isNotEmpty(all)) {
            return all;
        }
        return getKzzAndStock();
    }
}
